package com.hzgj.bcl.soa.cicada.pool;

import com.google.common.collect.Maps;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentMap;

import io.netty.channel.Channel;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;

public class Channels {

    private static final Logger logger = LoggerFactory.getLogger(Channels.class);
    private static final AttributeKey<Object> CHANNEL_REQUEST = AttributeKey.newInstance("channel_request");
    private static final ConcurrentMap<Long, Channel> channelMap = Maps.newConcurrentMap();

    public static Object getAttribute(Channel channel) {
        Attribute<Object> attr = channel.attr(CHANNEL_REQUEST);
        return attr != null ? attr.get() : null;
    }

    public static Object getAttribute(Channel channel, AttributeKey key) {
        Attribute<Object> attr = channel.attr(key);
        return attr != null ? attr.get() : null;
    }

    public static void setAttribute(Channel channel, Object o) {
        channel.attr(CHANNEL_REQUEST).set(o);
    }

    public static void setAttribute(Channel channel, AttributeKey key, Object o) {
        channel.attr(key).set(o);
    }

    public static void removeAttribute(Channel channel) {
        channel.attr(CHANNEL_REQUEST).set(null);
    }

    public static boolean isChannelValid(Channel channel) {
        return channel != null && channel.isActive();
    }

    public static void setDiscard(Channel channel) {
        setAttribute(channel, DiscardEvent.INSTANCE);
    }

    public static void silentlyCloseChannel(Channel channel) {
        try {
            if (channel != null && channel.isActive()) {
                channel.close();
            }
        } catch (Throwable t) {
            logger.debug("Failed to closeChannel channel", t);
        }
    }

    public static Channel addChannel(Long req_id, Channel ch) {
        if (ch == null) {
            return null;
        }
        Channel ret = channelMap.get(req_id);
        if (ret == null) {
            if (isChannelValid(ch)) {
                ret = channelMap.putIfAbsent(req_id, ch);
            }
        }
        return ret;
    }

    public static Channel getChannel(Long req_id) {
        return channelMap.remove(req_id);
    }

    public enum DiscardEvent {
        INSTANCE
    }
}
